using System.Collections.Generic;
using System.Text;

namespace OracleInternal.SqlAndPlsqlParser.LocalParsing
{
	internal class OracleLpFromClause : OracleLpFromClauseBase
	{
		protected List<OracleLpTableReference> m_vTableReferences;

		protected List<OracleLpStatementDataContainer> m_vTerms = new List<OracleLpStatementDataContainer>();

		protected List<OracleLpTableReference> TableReferences
		{
			get
			{
				if (m_vTableReferences == null)
				{
					m_vTableReferences = new List<OracleLpTableReference>();
					foreach (OracleLpFromListTerm term in Terms)
					{
						m_vTableReferences.Add(term.TableReference);
						if (term.Type != OracleLpFromListTermType.JoinClause)
						{
							continue;
						}
						foreach (OracleLpSpecificJoinClause joinClause in term.JoinClauses)
						{
							m_vTableReferences.Add(joinClause.TableReference);
						}
					}
				}
				return m_vTableReferences;
			}
		}

		public override List<OracleLpStatementDataContainer> Terms => m_vTerms;

		public OracleLpFromClause(OracleLpStatementElement parent)
			: base(parent)
		{
		}

		public override OracleLpColumnDescriptor FindColumn(OracleLpName schema, OracleLpName parent, OracleLpName colName)
		{
			OracleLpColumnDescriptor oracleLpColumnDescriptor = null;
			OracleLpColumnDescriptor oracleLpColumnDescriptor2 = null;
			string text = parent?.DbName;
			string text2 = schema?.DbName;
			string text3 = colName?.DbName;
			if (text == null)
			{
				foreach (OracleLpStatementDataContainer term in Terms)
				{
					foreach (OracleLpColumnDescriptor columnDescriptor in term.ColumnDescriptors)
					{
						if (columnDescriptor.ColumnName.DbName == text3)
						{
							if (oracleLpColumnDescriptor2 != null)
							{
								throw new OracleLpException(OracleLpExceptionType.AmbiguousDefinition, OracleLpExceptionError.AmbiguousColumn, string.Format(OracleLpErrorStrings.GetErrorString(OracleLpExceptionError.AmbiguousColumn), text3));
							}
							oracleLpColumnDescriptor2 = columnDescriptor;
						}
					}
				}
				if (oracleLpColumnDescriptor2 == null)
				{
					oracleLpColumnDescriptor = new OracleLpColumnDescriptor();
					oracleLpColumnDescriptor.BaseColumnName = colName;
					oracleLpColumnDescriptor.ColumnName = colName;
				}
				else
				{
					oracleLpColumnDescriptor = new OracleLpColumnDescriptor(oracleLpColumnDescriptor2);
					oracleLpColumnDescriptor.IsShowing = true;
				}
			}
			else
			{
				IOracleLpColumnDescriptorContainer oracleLpColumnDescriptorContainer = FindColumnContainer(schema, parent);
				if (oracleLpColumnDescriptorContainer == null)
				{
					throw new OracleLpException(OracleLpExceptionType.MissingReference, OracleLpExceptionError.MissingTable_View_Query, string.Format(OracleLpErrorStrings.GetErrorString(OracleLpExceptionError.MissingTable_View_Query), (text2 == null) ? "*" : text2, text));
				}
				foreach (OracleLpColumnDescriptor columnDescriptor2 in oracleLpColumnDescriptorContainer.ColumnDescriptors)
				{
					if (columnDescriptor2.ColumnName.DbName == text3)
					{
						oracleLpColumnDescriptor2 = columnDescriptor2;
						break;
					}
				}
				if (oracleLpColumnDescriptor2 == null)
				{
					throw new OracleLpException(OracleLpExceptionType.MissingReference, OracleLpExceptionError.MissingColumnFromReference, string.Format(OracleLpErrorStrings.GetErrorString(OracleLpExceptionError.MissingColumnFromReference), text3, text));
				}
				oracleLpColumnDescriptor = new OracleLpColumnDescriptor(oracleLpColumnDescriptor2);
				oracleLpColumnDescriptor.IsShowing = true;
			}
			return oracleLpColumnDescriptor;
		}

		public override IOracleLpColumnDescriptorContainer FindColumnContainer(OracleLpName schema, OracleLpName parent)
		{
			string text = parent?.DbName;
			if (text == null)
			{
				return TableReferences[0];
			}
			OracleLpTableReference result = null;
			foreach (OracleLpTableReference tableReference in TableReferences)
			{
				string text2 = ((tableReference.Alias == null) ? null : tableReference.Alias.DbName);
				if (text2 != null && text2 == text)
				{
					return tableReference;
				}
				if (tableReference.QueryTableExpression.QueryTableExpressionType == OracleLpQueryTableExpressionType.NamedObject)
				{
					OracleLpQteNamedObject oracleLpQteNamedObject = (OracleLpQteNamedObject)tableReference.QueryTableExpression;
					if (((oracleLpQteNamedObject.ObjectName == null) ? null : oracleLpQteNamedObject.ObjectName.DbName) == text && (schema == null || schema.DbName == ((oracleLpQteNamedObject.SchemaName == null) ? null : oracleLpQteNamedObject.SchemaName.DbName)))
					{
						return tableReference;
					}
				}
			}
			return result;
		}

		public override OracleLpQteNamedObject FindNamedObject(OracleLpName schema, OracleLpName parent)
		{
			OracleLpTableReference oracleLpTableReference = (OracleLpTableReference)FindColumnContainer(schema, parent);
			if (oracleLpTableReference != null && oracleLpTableReference.QueryTableExpression.QueryTableExpressionType == OracleLpQueryTableExpressionType.NamedObject)
			{
				return (OracleLpQteNamedObject)oracleLpTableReference.QueryTableExpression;
			}
			return null;
		}

		internal override void ToString(StringBuilder sb)
		{
			string depthIndent = base.DepthIndent;
			sb.Append(depthIndent);
			sb.Append("From List:\n");
			m_vTerms.ForEach(delegate(OracleLpStatementDataContainer ft)
			{
				ft.ToString(sb);
			});
		}
	}
}
